package com.hsu.hsurpc;

import com.hsu.hsurpc.config.RegistryConfig;
import com.hsu.hsurpc.config.RpcConfig;
import com.hsu.hsurpc.constant.RpcConstant;
import com.hsu.hsurpc.registry.Registry;
import com.hsu.hsurpc.registry.RegistryFactory;
import com.hsu.hsurpc.utils.ConfigUtils;
import lombok.extern.slf4j.Slf4j;

import java.nio.charset.StandardCharsets;

/**
 * RPC 框架应用
 * 负责存放项目全局用到的变量，使用双检锁单例模式实现
 * @Author Hsu琛君珩
 * @Date 2024-09-18 13:59
 * @Description
 * @Version: v1.0.0
 */
@Slf4j
public class RpcApplication {

    // 全局 RPC 配置对象，使用 volatile 保证线程安全
    private static volatile RpcConfig rpcConfig;

    /**
     * 框架初始化，支持传入自定义配置
     *
     * @param newRpcConfig 自定义的配置对象
     */
    public static void init(RpcConfig newRpcConfig) {
        // 将传入的配置对象赋值为全局配置对象
        rpcConfig = newRpcConfig;
        log.info("RPC initialized with config: {}", newRpcConfig.toString());

        // 初始化注册中心
        RegistryConfig registryConfig = rpcConfig.getRegistryConfig();
        Registry registry = RegistryFactory.getInstance(registryConfig.getRegistry());
        registry.init(registryConfig);
        log.info("registry init, config = {}", registryConfig);

        // 创建并注册 Shutdown Hook，JVM 退出时并执行操作
        Runtime.getRuntime().addShutdownHook(new Thread(registry::destroy));
    }

    /**
     * 默认初始化
     */
    public static void init() {
        RpcConfig newRpcConfig;
        try {
            // 尝试从配置文件加载配置对象，使用 UTF-8 编码
            newRpcConfig = ConfigUtils.loadConfig(RpcConfig.class, RpcConstant.DEFAULT_CONFIG_PREFIX, StandardCharsets.UTF_8);
        } catch (Exception e) {
            // 如果加载失败，使用默认的配置对象
            newRpcConfig = new RpcConfig();
        }
        // 使用加载到的配置对象初始化全局配置
        init(newRpcConfig);;
    }

    /**
     * 获取全局配置
     *
     * @return 配置对象
     */
    public static RpcConfig getRpcConfig() {
        // 双检锁单例模式，确保配置只被加载一次
        if (rpcConfig == null) {
            synchronized (RpcApplication.class) {
                if (rpcConfig == null) {
                    init();
                    log.info("RpcConfig loaded: {}", rpcConfig);
                }
            }
        }
        return rpcConfig;
    }

}
